package com.onlyxiahui.ability.basic.util.io.file;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.HashMap;
import java.util.Map;

public class FileLockUtil {
	
	static Map<String, FileLockData> map = new HashMap<String, FileLockData>();

	public static boolean tryLock(String filePath) {
		boolean get = false;
		synchronized (map) {
			FileLockData fld = map.get(filePath);
			if (null == fld) {
				fld = new FileLockData(filePath);
				map.put(filePath, fld);
			}
			get = fld.tryLock();
		}
		return get;
	}

	public static void releaseLock(String filePath) {
		FileLockData fld = map.remove(filePath);
		if (null != fld) {
			fld.release();
		}
	}
}

class FileLockData {

	final File file;
	RandomAccessFile randomAccessFile;
	FileLock fileLock;
	FileChannel fileChannel;

	public FileLockData(String filePath) {
		file = new File(filePath);
		try {
			randomAccessFile = new RandomAccessFile(file, "rw");
			fileChannel = randomAccessFile.getChannel();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public RandomAccessFile getRandomAccessFile() {
		return randomAccessFile;
	}

	public FileLock getFileLock() {
		return fileLock;
	}

	public FileChannel getFileChannel() {
		return fileChannel;
	}

	public boolean tryLock() {
		boolean get = false;

		if (null == fileLock) {
			try {
				fileLock = fileChannel.tryLock();
				if (null != fileLock) {
					get = fileLock.isValid();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			get = fileLock.isValid();
		}
		return get;
	}

	public void release() {
		if (null != fileLock) {
			try {
				fileLock.release();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (null != fileChannel) {
			try {
				fileChannel.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (null != randomAccessFile) {
			try {
				randomAccessFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}